﻿using System;
using System.Collections.Generic;
using System.Reflection;
using ShureValidation.Rules;

namespace ShureValidation.Fluent
{
    public class FluentValidator<T> : FluentValidator
    {
        public FluentValidator()
            : base(typeof(T))
        {
        }

    }

    public class FluentValidator
    {
        Dictionary<string, Property> _properties = new Dictionary<string, Property>();
        ModelValidator _validator = new ModelValidator();
        private Type _type;

        public FluentValidator(Type type)
        {
            _type = type;
        }

        protected Property Property(string name)
        {
            Property property;
            if (_properties.TryGetValue(name, out property))
                return property;

            var pi = _type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
            if (pi == null || !pi.CanRead || !pi.CanWrite)
                throw new InvalidOperationException(_type.FullName + " do not have a read/writable property named '" +
                                                    name + "'.");

            property = new Property(name, _validator);
            _properties.Add(name, property);
            return property;
        }

        internal ModelValidator GetValidator()
        {
            return _validator;
        }
    }

    public class Property
    {
        private readonly string _name;
        private readonly ModelValidator _validator;

        public Property(string name, ModelValidator validator)
        {
            _name = name;
            _validator = validator;
        }

        public Property Max(int length)
        {
            _validator.Add(_name, new MaxRule(length));
            return this;
        }

        public Property Min(int length)
        {
            _validator.Add(_name, new MinRule(length));
            return this;
        }

        public Property Required()
        {
            _validator.Add(_name, new RequiredRule());
            return this;
        }
    }
}
